/*********************************************************************
 * INCLUDES
 */
#include "OSAL.h"
#include "gpio.h"
#include "clock.h"
#include "adc.h"
#include "halPeripheral.h"
#include "log.h"
#include "user_fifo.h"

#ifndef PRV_ADC_TEST
    #define PRV_ADC_TEST 0
#endif
/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
#define MAX_SAMPLE_POINT    64
uint16_t adc_debug[6][MAX_SAMPLE_POINT];
uint16_t sendadc[MAX_SAMPLE_POINT];
#if(PRV_ADC_TEST == 0)
static uint8_t channel_done_flag = 0;
#endif
user_fifo_t uart_fifo;
uint8 uart_recv_buf[UART_BUF_SIZE];
/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */
 
/*********************************************************************
 * LOCAL VARIABLES
 */
uint8 adcDemo_TaskID;   // Task ID for internal task/event processing
/*
channel:
is_high_resolution:
[bit7~bit2]=[p20,p15~p11],ignore[bit1,bit0]
when measure adc(not battery),we'd better use high_resolution.
when measure battery,we'd better use no high_resolution and keep the gpio alone.
ADC_BIT(ADC_CH3P_P20)|ADC_BIT(ADC_CH2P_P14)|ADC_BIT(ADC_CH3N_P15)|ADC_BIT(ADC_CH1N_P11)|ADC_BIT(ADC_CH2N_P24)|ADC_BIT(ADC_CH1P_P23)
ADC_BIT(ADC_CH3P_P20)|ADC_BIT(ADC_CH1N_P11)|ADC_BIT(ADC_CH2N_P24)|ADC_BIT(ADC_CH1P_P23)|ADC_BIT(ADC_CH3N_P15),
*/
AdcCfg_t adc_cfg = {	

	.channel_flag = ADC_BIT(ADC_CH3P_P20)|ADC_BIT(ADC_CH2P_P14)|ADC_BIT(ADC_CH3N_P15),
	.is_continue_mode = TRUE,
    .is_high_resolution = 0x7f,
};




/*********************************************************************
 * LOCAL FUNCTIONS
 */
static void adcMeasureTask( void );

/*********************************************************************
 * PROFILE CALLBACKS
 */

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

void HalPeripheral_Init( uint8 task_id )
{
	adcDemo_TaskID = task_id;
	HalAdcInit();
	adcMeasureTask();
	user_fifo_init(&uart_fifo, uart_recv_buf, UART_BUF_SIZE);
	osal_start_timerEx(adcDemo_TaskID, adcMeasureTask_EVT,10);
}

uint16 HalPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{  
    VOID task_id; // OSAL required parameter that isn't used in this function
    //LOG("HalPeripheral_ProcessEvent: 0x%x\n",events);

    if ( events & SYS_EVENT_MSG )
    {

        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
    }
 
    if ( events & sendadc_EVT )
    {

	   
        //osal_start_timerEx( adcDemo_TaskID, 0x20, 2000);    
        return (events ^ sendadc_EVT);
    }  

    if ( events & adcMeasureTask_EVT )
    {
        // Perform periodic heart rate task
        //LOG("adcMeasureTask_EVT\n");
        adcMeasureTask();    
        return (events ^ adcMeasureTask_EVT);
    }  
  
    // Discard unknown events
    return 0;
}


static void adc_evt(AdcEvt_t* pev)
{	
	
	
#if(PRV_ADC_TEST == 1)
	if((pev->type != HAL_ADC_EVT_DATA) || (pev->ch < 2))
		return;
	if(pev->ch ==  ADC_CH3N_P15)
	{
		user_set_fifo_data(&uart_fifo,(uint8_t *) pev->data, 2* pev->size);
		osal_set_event(adcDemo_TaskID, sendadc_EVT);
	}
	
#else
	float value = 0;
	int i = 0;
	bool is_high_resolution = FALSE;
	uint8_t ch = 0;
	
	if((pev->type != HAL_ADC_EVT_DATA) || (pev->ch < 2))
		return;
	osal_memcpy(adc_debug[pev->ch-2],pev->data,2*(pev->size));
	channel_done_flag |= BIT(pev->ch);		
		
	if(channel_done_flag == adc_cfg.channel_flag)
	{        		
		for(i=2;i<8;i++)
		{
			if(channel_done_flag & BIT(i))
			{
				is_high_resolution = (adc_cfg.is_high_resolution & BIT(i))?TRUE:FALSE;
				value = HalAdcValueCal((AdcChannel_t)i,adc_debug[i-2], pev->size, is_high_resolution);
				switch(i)
				{
					case ADC_CH1N_P11:
						ch=11;
						break;
					case ADC_CH1P_P23:
						ch=23;
						break;
					case ADC_CH2N_P24:
						ch=24;
						break;
					case ADC_CH2P_P14:
						ch=14;
						break;
					case ADC_CH3N_P15:
						ch=15;
						break;
					case ADC_CH3P_P20:
						ch=20;
						break;
					default:
						break;
				}
				
				if(ch!=0)
				{
					LOG("P%d %d mv \r\n",ch,(int)(value));
					
				}
				else
				{
					LOG("invalid channel\n");
				}					
			}
		}			
//		LOG(" mode:%d \n",adc_cfg.is_continue_mode);		
		channel_done_flag = 0;
		
		if(adc_cfg.is_continue_mode == FALSE)
		{
			osal_start_timerEx(adcDemo_TaskID, adcMeasureTask_EVT,1000);
		}
	}   
#endif	
}
uint8_t	ADC_CH_Flag = 0;
static void adcMeasureTask( void )
{	
		ADC_CH_Flag ++;
		if(ADC_CH_Flag == 6)
			ADC_CH_Flag = 0 ;

		
	HalAdcChannelConfig(adc_cfg, adc_evt);
	subWriteReg(0x4000F000 + 0x7c,3,3,0);
	HalAdcStart();
}

